/** ****************************************************************************
* @addtogroup BSP
* @{
*******************************************************************************/

#ifndef __MCU_H
#define __MCU_H

#include "mcu_compliant.h"


#define MCU_SERIES_MSP430

// STM8 系列 MCU 是 2 字节对齐
#define portBYTE_ALIGNMENT			2
#define portPOINTER_SIZE_TYPE		sizeof(void*)

#ifndef __BIG_ENDIAN__
	#define __BIG_ENDIAN__			0
#endif
#ifndef __LITTLE_ENDIAN__
	#define __LITTLE_ENDIAN__		1
#endif

#if (__LITTLE_ENDIAN__ == 1)
	// 网络字节顺序采用 big endian 排序方式
	// 所以如果 MCU 的字节序是 little endian 方式时，需要进行转换
	#define ntoh32(dw) 	BL32(dw)
	#define ntoh16(w) 	BL16(w)
	#define hton32(dw) 	BL32(dw)
	#define hton16(w) 	BL16(w)
#else
	#define ntoh32(dw) 	(dw)
	#define ntoh16(w) 	(w)
	#define hton32(dw) 	(dw)
	#define hton16(w) 	(w)
#endif

#if (defined __ICCSTM8__)
	#define ASM  asm
#else
	//#error "Unsupported Compiler!"
#endif

#define INLINE	_Pragma("inline=forced")

/// Base
#define disableInterrupts() __disable_interrupt()
#define enableInterrupts()  __enable_interrupt()
#define NOP()   			__no_operation()


//
// IO口操作宏定义
//
// GPIN Registers I/O
#define GPIN_SEL_CFG_Io(PORT, PIN)				((PORT##SEL2 &= ~BV(PIN)), (PORT##SEL &= ~BV(PIN)))	// SEL2=0, SEL=0: I/O function is selected
#define GPIN_SEL_CFG_AF1(PORT, PIN)				((PORT##SEL2 &= ~BV(PIN)), (PORT##SEL |=  BV(PIN)))	// SEL2=0, SEL=1: Primary peripheral module function is selected
#define GPIN_SEL_CFG_AF2(PORT, PIN)				((PORT##SEL2 |=  BV(PIN)), (PORT##SEL |=  BV(PIN)))	// SEL2=1, SEL=1: Secondary peripheral module function is selected

#define GPIN_DIR_CFG_Input(PORT, PIN)			(PORT##DIR   &= ~BV(PIN))	// DIR=0: 表示输入模式
#define GPIN_DIR_CFG_Output(PORT, PIN)			(PORT##DIR   |=  BV(PIN))	// DIR=1: 表示输出模式

#define GPIN_REN_CFG_NoPP(PORT, PIN)			(PORT##REN   &= ~BV(PIN))	// REN=0: No Push-Pull
#define GPIN_REN_CFG_PP(PORT, PIN)				(PORT##REN   |=  BV(PIN))	// REN=1: Push-Pull

#define GPIN_IE_CFG_Disable(PORT, PIN)			(PORT##IE    &= ~BV(PIN))	// IE=0: External interrupt disabled
#define GPIN_IE_CFG_Enable(PORT, PIN)			(PORT##IE    |=  BV(PIN))	// IE=1: External interrupt enabled

#define GPIN_IES_CFG_Rising(PORT, PIN)			(PORT##IES   &= ~BV(PIN))	// IES=0: EXTI on Rising
#define GPIN_IES_CFG_Falling(PORT, PIN)			(PORT##IES   |=  BV(PIN))	// IES=1: EXTI on Falling

#define GPIN_ReadIn(PORT, PIN)      			((PORT##IN  & BV(PIN)) != 0)
#define GPIN_ReadOut(PORT, PIN)					((PORT##OUT & BV(PIN)) != 0)
#define GPIN_WriteOut(PORT, PIN, x)				((x)?(PORT##OUT |= BV(PIN)):(PORT##OUT &= ~BV(PIN)))
#define GPIN_Toggle(PORT, PIN)					(PORT##OUT ^= BV(PIN))

#define GPIN_EXTI_Flag(PORT, PIN)				((PORT##IFG & BV(PIN)) != 0)
#define GPIN_EXTI_Clear(PORT, PIN)				( PORT##IFG &= ~BV(PIN))

// GPIN_CFG 可能的模式定义(共12种)
// bit[3]: SEL2
// bit[2]: SEL
// bit[1]: DIR
// bit[0]: REN
#define GPIN_CFG_In_Floating		0x00
#define GPIN_CFG_In_PP				0x01
#define GPIN_CFG_Out				0x02
#define GPIN_CFG_Out_PP				0x03

#define GPIN_CFG_AF1_In_Floating	0x04
#define GPIN_CFG_AF1_In_PP			0x05
#define GPIN_CFG_AF1_Out			0x06
#define GPIN_CFG_AF1_Out_PP			0x07

#define GPIN_CFG_AF2_In_Floating	0x0C
#define GPIN_CFG_AF2_In_PP			0x0D
#define GPIN_CFG_AF2_Out			0x0E
#define GPIN_CFG_AF2_Out_PP			0x0F

// GPIN APIs
#define GPIN_Config(PORT, PIN, CFG) (\
	((CFG & BV(3)) ? (PORT##SEL2 |= BV(PIN)) : (PORT##SEL2 &= ~BV(PIN))), \
	((CFG & BV(2)) ? (PORT##SEL  |= BV(PIN)) : (PORT##SEL  &= ~BV(PIN))), \
	((CFG & BV(1)) ? (PORT##DIR  |= BV(PIN)) : (PORT##DIR  &= ~BV(PIN))), \
	((CFG & BV(0)) ? (PORT##REN  |= BV(PIN)) : (PORT##REN  &= ~BV(PIN))) )

#define GPIN_ConfigX(PORT, PIN, CFG, x)		(GPIN_Config(PORT, PIN, CFG), GPIN_WriteOut(PORT, PIN, x))

// 未使用的引脚默认配置
// 为了节能，对于未使用的 I/O 口，不能悬空(未连接/或高阻)，就必须配置为三种之一: 上拉输入、下拉输入、下拉输出
#define GPIN_ConfigUnuseAs_IPU(PORT, PIN) 					GPIN_ConfigX(PORT, PIN, GPIN_CFG_In_PP, 1)
#define GPIN_ConfigUnuseAs_IPD(PORT, PIN) 					GPIN_ConfigX(PORT, PIN, GPIN_CFG_In_PP, 0)
#define GPIN_ConfigUnuseAs_Out_PP_High(PORT, PIN) 			GPIN_ConfigX(PORT, PIN, GPIN_CFG_Out_PP, 1)
#define GPIN_ConfigUnuseAs_Out_PP_Low(PORT, PIN) 			GPIN_ConfigX(PORT, PIN, GPIN_CFG_Out_PP, 0)
#define GPIO_Unuse(PORT, PIN) 								GPIN_ConfigUnuseAs_Out_PP_High(PORT, PIN)

// 命名的 GPIO APIs
#define GPIO_DEFINE(NAME, PORT, PIN) \
INLINE void GPIO_##NAME##_Config(uint8_t cfg)					{ GPIN_Config(PORT, PIN, cfg); } \
INLINE void GPIO_##NAME##_ConfigX(uint8_t cfg, uint8_t x)				{ GPIN_ConfigX(PORT, PIN, cfg, x); } \
INLINE void GPIO_##NAME##_Toggle()      					{ GPIN_Toggle(PORT, PIN); } \
INLINE uint8_t   GPIO_##NAME##_ReadIn()      					{ return GPIN_ReadIn(PORT, PIN); } \
INLINE uint8_t   GPIO_##NAME##_ReadOut()     					{ return GPIN_ReadOut(PORT, PIN); } \
INLINE void GPIO_##NAME##_Out(uint8_t x)  						{ GPIN_WriteOut(PORT, PIN, x); } \
INLINE uint8_t   GPIO_##NAME##_IntFlag()							{ return GPIN_EXTI_Flag(PORT, PIN); } \
INLINE void GPIO_##NAME##_IntClear()						{ GPIN_EXTI_Clear(PORT, PIN); } \
INLINE void GPIO_##NAME##_IntEnable(uint8_t trigger, uint8_t enable)	{ trigger?GPIN_IES_CFG_Falling(PORT, PIN):GPIN_IES_CFG_Rising(PORT, PIN); enable?GPIN_IE_CFG_Enable(PORT, PIN):GPIN_IE_CFG_Disable(PORT, PIN); } \
INLINE void GPIO_##NAME##_BidiConfig(uint8_t ci, uint8_t co, uint8_t io)	{ static uint8_t sci=0xFF,sco=0xFF,sio=0xF5; (sio==0xF5)?(sci=ci, sco=co):(0); (io==sio)?(0):(GPIO_##NAME##_Config((io==INPUT)?sci:sco), sio=io); } \
INLINE void GPIO_##NAME##_BidiSwitch(uint8_t io)					{ GPIO_##NAME##_BidiConfig(0, 0, io); } \
INLINE uint8_t   GPIO_##NAME##_BidiReadIn()						{ GPIO_##NAME##_BidiConfig(0, 0, INPUT); return GPIO_##NAME##_ReadIn(); } \
INLINE void GPIO_##NAME##_BidiOut(uint8_t x)  					{ GPIO_##NAME##_BidiConfig(0, 0, OUTPUT); GPIO_##NAME##_Out(x); }

#define GPIO_DEFINE_POLARITY(NAME, PORT, PIN, LEVEL) \
GPIO_DEFINE(NAME, PORT, PIN)\
INLINE void GPIO_##NAME##_On()          					{ GPIO_##NAME##_Out(LEVEL); } \
INLINE void GPIO_##NAME##_Off()         					{ GPIO_##NAME##_Out(!LEVEL); } \
INLINE void GPIO_##NAME##_Switch(uint8_t on)  					{ (!on == !LEVEL)?GPIO_##NAME##_Out(1):GPIO_##NAME##_Out(0); } \
INLINE uint8_t   GPIO_##NAME##_IsOutOn()     					{ return (GPIO_##NAME##_ReadOut() == LEVEL); } \
INLINE uint8_t   GPIO_##NAME##_IsOutOff()    					{ return (GPIO_##NAME##_ReadOut() != LEVEL); } \
INLINE uint8_t   GPIO_##NAME##_IsInOn()      					{ return (GPIO_##NAME##_ReadIn() == LEVEL); } \
INLINE uint8_t   GPIO_##NAME##_IsInOff()     					{ return (GPIO_##NAME##_ReadIn() != LEVEL); } \
INLINE uint8_t   GPIO_##NAME##_Polarity()      					{ return LEVEL; }

//
// 关于 Watchdog
//
/// @brief 看门狗禁用
#define Watchdog_disable()	(WDTCTL = WDTPW + WDTHOLD)
/// @brief 喂看门狗
#define Watchdog_feed()		IWDG_ReloadCounter()

//
// 关于 Flash 的定义
//
#define FLASH_PAGE_SIZE 						FLASH_BLOCK_SIZE
//#define FLASH_PROGRAM_START_PHYSICAL_ADDRESS  0x8000
#define RAM_START_PHYSICAL_ADDRESS            	0x0000

//
// 关于中断向量表的定义
//
#define MCU_ENTRY		    FLASH_PROGRAM_START_PHYSICAL_ADDRESS
#define INTVEC_SIZE         0x80
#define OPCODE_INT_ADDR_EXT 0x8200

typedef struct stIntVectorItem {
	uint16_t code;   // = OPCODE_INT + ADDR_EXT
	uint16_t isr;    // = FUNC_void_voidp
} IntVectorItem;

/// 判断一个地址是否一个正确的程序入口地址（包括包括正确的 栈地址 和 中断向量表）
int isValidEntry(uint16_t entry);

/// 跳转到 Bootloader 中去执行(当前程序中止)
void jump2Entry(uint16_t entry);

// 系统重启：使用 WWDG (窗口看门狗)产生一个复位信号
#define systemReset()   WWDG_SWReset()

// 是否是在进行调试
int isInDebugging();


#endif  // __MCU_H
/// @}
